
/*
 * Copyright 2002-2018 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 *版权所有2002-2018原作者。
 *
 *根据Apache许可证2.0版（“许可证”）获得许可；
 *除非符合许可证，否则不得使用此文件。
 *您可以在以下地址获取许可证副本：
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 *除非适用法律要求或书面同意，软件
 *根据许可证分发的内容是按“原样”分发的，
 *无任何明示或暗示的保证或条件。
 *有关管理权限和
 *许可证下的限制。
 */

package org.springframework.beans.factory.xml;

import org.w3c.dom.Element;

import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;

/**
 * Abstract {@link BeanDefinitionParser} implementation providing
 * a number of convenience methods and a
 * {@link AbstractBeanDefinitionParser#parseInternal template method}
 * that subclasses must override to provide the actual parsing logic.
 *
 * <p>Use this {@link BeanDefinitionParser} implementation when you want
 * to parse some arbitrarily complex XML into one or more
 * {@link BeanDefinition BeanDefinitions}. If you just want to parse some
 * XML into a single {@code BeanDefinition}, you may wish to consider
 * the simpler convenience extensions of this class, namely
 * {@link AbstractSingleBeanDefinitionParser} and
 * {@link AbstractSimpleBeanDefinitionParser}.
 *
 * @author Rob Harrop
 * @author Juergen Hoeller
 * @author Rick Evans
 * @author Dave Syer
 * @since 2.0
 */
/**
 *抽象｛@link BeanDefinitionParser｝实现提供
 *许多方便的方法和
 *｛@link AbstractBeanDefinitionParser#parseInternal模板方法｝
 *子类必须重写以提供实际的解析逻辑。
 *
 *＜p＞需要时使用此｛@link BeanDefinitionParser｝实现
 *将一些任意复杂的XML解析为一个或多个
 *｛@link BeanDefinition BeanDefinitions｝。如果你只是想解析一些
 *将XML转换为单个｛@code BeanDefinition｝，您可能希望考虑
 *这个类的简单方便扩展，即
 *｛@link AbstractSingleBeanDefinitionParser｝和
 *｛@link AbstractSimpleBeanDefinitionParser｝。
 *
 *@作者Rob Harrop
 *@作者Juergen Hoeller
 *@作者Rick Evans
 *@作者Dave Syer
 *@自2.0起
 */
public abstract class AbstractBeanDefinitionParser implements BeanDefinitionParser {

	/** Constant for the "id" attribute. */
	public static final String ID_ATTRIBUTE = "id";

	/** Constant for the "name" attribute. */
	public static final String NAME_ATTRIBUTE = "name";


	@Override
	@Nullable
	public final BeanDefinition parse(Element element, ParserContext parserContext) {
		AbstractBeanDefinition definition = parseInternal(element, parserContext);
		if (definition != null && !parserContext.isNested()) {
			try {
				String id = resolveId(element, definition, parserContext);
				if (!StringUtils.hasText(id)) {
					parserContext.getReaderContext().error(
							"Id is required for element '" + parserContext.getDelegate().getLocalName(element)
									+ "' when used as a top-level tag", element);
				}
				String[] aliases = null;
				if (shouldParseNameAsAliases()) {
					String name = element.getAttribute(NAME_ATTRIBUTE);
					if (StringUtils.hasLength(name)) {
						aliases = StringUtils.trimArrayElements(StringUtils.commaDelimitedListToStringArray(name));
					}
				}
				BeanDefinitionHolder holder = new BeanDefinitionHolder(definition, id, aliases);
				registerBeanDefinition(holder, parserContext.getRegistry());
				if (shouldFireEvents()) {
					BeanComponentDefinition componentDefinition = new BeanComponentDefinition(holder);
					postProcessComponentDefinition(componentDefinition);
					parserContext.registerComponent(componentDefinition);
				}
			}
			catch (BeanDefinitionStoreException ex) {
				String msg = ex.getMessage();
				parserContext.getReaderContext().error((msg != null ? msg : ex.toString()), element);
				return null;
			}
		}
		return definition;
	}

	/**
	 * Resolve the ID for the supplied {@link BeanDefinition}.
	 * <p>When using {@link #shouldGenerateId generation}, a name is generated automatically.
	 * Otherwise, the ID is extracted from the "id" attribute, potentially with a
	 * {@link #shouldGenerateIdAsFallback() fallback} to a generated id.
	 * @param element the element that the bean definition has been built from
	 * @param definition the bean definition to be registered
	 * @param parserContext the object encapsulating the current state of the parsing process;
	 * provides access to a {@link org.springframework.beans.factory.support.BeanDefinitionRegistry}
	 * @return the resolved id
	 * @throws BeanDefinitionStoreException if no unique name could be generated
	 * for the given bean definition
	 */
	/** Constant for the "id" attribute. */
	公共静态最终字符串ID_ATTRIBUTE=“ID”；

	/**“name”属性的常量*/
	公共静态最终字符串NAME_ATTRIBUTE=“NAME”；


	@覆盖
	@可为空
	public final BeanDefinition parse（Element元素，ParserContext ParserContext）{
		AbstractBeanDefinition定义=parseInternal（元素，parserContext）；
		if（definition！=null&&！parserContext.isNested（））{
			尝试{
				字符串id=resolveId（元素，定义，parserContext）；
				if（！StringUtils.hasText（id））{
					parserContext.getReaderContext（）.error(
							“元素“”+parserContext.getDelegate（）.getLocalName（元素）需要Id
									+“'用作顶级标记时”，元素）；
				}
				String[]别名=null；
				if（shouldParseNameAsAliases（））{
					字符串名称=元素.getAttribute（name_ATTRIBUTE）；
					if（StringUtils.hasLength（name））{
						alias=StringUtils.trimArrayElements（StringUtils.commaDelimitedListToStringArray（名称））；
					}
				}
				BeanDefinitionHolder=新的BeanDefinitionHolder（定义、id、别名）；
				registerBeanDefinition（holder，parserContext.getRegistry（））；
				if（shouldFireEvents（））{
					BeanComponentDefinition componentDefinition=新的BeanComponentDefinition（持有者）；
					postProcessComponentDefinition（组件定义）；
					parserContext.registerComponent（componentDefinition）；
				}
			}
			catch（BeanDefinitionStoreException ex）{
				字符串msg=例如getMessage（）；
				parserContext.getReaderContext（）.error（（msg！=null？msg:ex.toString（），元素）；
				返回null；
			}
		}
		返回定义；
	}

	/**
	 *解析提供的｛@link BeanDefinition｝的ID。
	 *＜p＞使用｛@link#shouldGenerateId generation｝时，将自动生成名称。
	 *否则，将从“ID”属性中提取ID，可能使用
	 *｛@link#shouldGenerateIdAsFallback（）回退｝到生成的id。
	 *@param元素——构建bean定义的元素
	 *@param definition要注册的bean定义
	 *@param parserContext封装解析过程当前状态的对象；
	 *提供对｛@link org.springframework.beans.factory.support.BeanDefinitionRegistry｝的访问
	 *@返回已解析的id
	 *如果无法生成唯一名称，@throws BeanDefinitionStoreException
	 *对于给定的bean定义
	 */
	protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
			throws BeanDefinitionStoreException {

		if (shouldGenerateId()) {
			return parserContext.getReaderContext().generateBeanName(definition);
		}
		else {
			String id = element.getAttribute(ID_ATTRIBUTE);
			if (!StringUtils.hasText(id) && shouldGenerateIdAsFallback()) {
				id = parserContext.getReaderContext().generateBeanName(definition);
			}
			return id;
		}
	}

	/**
	 * Register the supplied {@link BeanDefinitionHolder bean} with the supplied
	 * {@link BeanDefinitionRegistry registry}.
	 * <p>Subclasses can override this method to control whether the supplied
	 * {@link BeanDefinitionHolder bean} is actually even registered, or to
	 * register even more beans.
	 * <p>The default implementation registers the supplied {@link BeanDefinitionHolder bean}
	 * with the supplied {@link BeanDefinitionRegistry registry} only if the {@code isNested}
	 * parameter is {@code false}, because one typically does not want inner beans
	 * to be registered as top level beans.
	 * @param definition the bean definition to be registered
	 * @param registry the registry that the bean is to be registered with
	 * @see BeanDefinitionReaderUtils#registerBeanDefinition(BeanDefinitionHolder, BeanDefinitionRegistry)
	 */
	/**
	 *使用提供的
	 *｛@link BeanDefinitionRegistry注册表｝。
	 *＜p＞子类可以重写此方法，以控制是否提供
	 *｛@link BeanDefinitionHolder bean｝实际上已经注册，或者
	 *注册更多的bean。
	 *＜p＞默认实现注册提供的｛@link BeanDefinitionHolder bean｝
	 *仅当｛@code是Nested｝时，才使用提供的｛@link BeanDefinitionRegistry注册表｝
	 *参数为｛@code false｝，因为通常不需要内部bean
	 *注册为顶级bean。
	 *@param definition要注册的bean定义
	 *@param registry要注册bean的注册表
	 *@参见BeanDefinitionReaderUtils#registerBeanDefinition（BeanDefinitionHolder，BeanDefinitionRegistry）
	 */
	protected void registerBeanDefinition(BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {
		BeanDefinitionReaderUtils.registerBeanDefinition(definition, registry);
	}


	/**
	 * Central template method to actually parse the supplied {@link Element}
	 * into one or more {@link BeanDefinition BeanDefinitions}.
	 * @param element the element that is to be parsed into one or more {@link BeanDefinition BeanDefinitions}
	 * @param parserContext the object encapsulating the current state of the parsing process;
	 * provides access to a {@link org.springframework.beans.factory.support.BeanDefinitionRegistry}
	 * @return the primary {@link BeanDefinition} resulting from the parsing of the supplied {@link Element}
	 * @see #parse(org.w3c.dom.Element, ParserContext)
	 * @see #postProcessComponentDefinition(org.springframework.beans.factory.parsing.BeanComponentDefinition)
	 */
	/**
	 *实际分析提供的｛@link Element｝的中心模板方法
	 *转换为一个或多个｛@link BeanDefinition BeanDefinitions｝。
	 *@param元素要解析为一个或多个｛@link BeanDefinition BeanDefinitions｝的元素
	 *@param parserContext封装解析过程当前状态的对象；
	 *提供对｛@link org.springframework.beans.factory.support.BeanDefinitionRegistry｝的访问
	 *@返回解析所提供的｛@link Element｝所产生的主｛@linkBeanDefinition｝
	 *@see#parse（org.w3c.dom.Element，ParserContext）
	 *@see#postProcessComponentDefinition（org.springframework.beans.factory.parsing.BeanComponentDefinition）
	 */
	@Nullable
	protected abstract AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext);

	/**
	 * Should an ID be generated instead of read from the passed in {@link Element}?
	 * <p>Disabled by default; subclasses can override this to enable ID generation.
	 * Note that this flag is about <i>always</i> generating an ID; the parser
	 * won't even check for an "id" attribute in this case.
	 * @return whether the parser should always generate an id
	 */
	/**
	 *是否应该生成ID而不是从传入的｛@link Element｝中读取？
	 *＜p＞默认禁用；子类可以覆盖它以启用ID生成。
	 *注意，此标志是关于生成ID的<i>始终</i>；解析器
	 *在这种情况下，甚至不会检查“id”属性。
	 *@return解析器是否应始终生成id
	 */
	protected boolean shouldGenerateId() {
		return false;
	}

	/**
	 * Should an ID be generated instead if the passed in {@link Element} does not
	 * specify an "id" attribute explicitly?
	 * <p>Disabled by default; subclasses can override this to enable ID generation
	 * as fallback: The parser will first check for an "id" attribute in this case,
	 * only falling back to a generated ID if no value was specified.
	 * @return whether the parser should generate an id if no id was specified
	 */
	/**
	 *如果传入的｛@link Element｝没有
	 *显式指定“id”属性？
	 *＜p＞默认禁用；子类可以覆盖此项以启用ID生成
	 *作为回退：在这种情况下，解析器将首先检查“id”属性，
	 *如果没有指定值，则返回到生成的ID。
	 *@return如果未指定id，解析器是否应生成id
	 */
	protected boolean shouldGenerateIdAsFallback() {
		return false;
	}

	/**
	 * Determine whether the element's "name" attribute should get parsed as
	 * bean definition aliases, i.e. alternative bean definition names.
	 * <p>The default implementation returns {@code true}.
	 * @return whether the parser should evaluate the "name" attribute as aliases
	 * @since 4.1.5
	 */
	/**
	 *确定元素的“name”属性是否应解析为
	 *bean定义别名，即替代bean定义名称。
	 *＜p＞默认实现返回｛@code true｝。
	 *@return解析器是否应将“name”属性求值为别名
	 *@自4.1.5起
	 */
	protected boolean shouldParseNameAsAliases() {
		return true;
	}

	/**
	 * Determine whether this parser is supposed to fire a
	 * {@link org.springframework.beans.factory.parsing.BeanComponentDefinition}
	 * event after parsing the bean definition.
	 * <p>This implementation returns {@code true} by default; that is,
	 * an event will be fired when a bean definition has been completely parsed.
	 * Override this to return {@code false} in order to suppress the event.
	 * @return {@code true} in order to fire a component registration event
	 * after parsing the bean definition; {@code false} to suppress the event
	 * @see #postProcessComponentDefinition
	 * @see org.springframework.beans.factory.parsing.ReaderContext#fireComponentRegistered
	 */
	/**
	 *确定此解析器是否应该激发
	 *｛@link org.springframework.beans.factory.parsing.BeanComponentDefinition｝
	 *事件。
	 *＜p＞此实现默认返回｛@code true｝；即，
	 *当bean定义被完全解析后，将触发一个事件。
	 *重写此以返回｛@code false｝以抑制事件。
	 *@return｛@code true｝以触发组件注册事件
	 *在解析bean定义之后；｛@code false｝以抑制事件
	 *@参见#postProcessComponentDefinition
	 *@see org.springframework.beans.factory.parsing.ReaderContext#fireComponentRegistered
	 */
	protected boolean shouldFireEvents() {
		return true;
	}

	/**
	 * Hook method called after the primary parsing of a
	 * {@link BeanComponentDefinition} but before the
	 * {@link BeanComponentDefinition} has been registered with a
	 * {@link org.springframework.beans.factory.support.BeanDefinitionRegistry}.
	 * <p>Derived classes can override this method to supply any custom logic that
	 * is to be executed after all the parsing is finished.
	 * <p>The default implementation is a no-op.
	 * @param componentDefinition the {@link BeanComponentDefinition} that is to be processed
	 */
	/**
	 *在
	 *｛@link BeanComponentDefinition｝，但在
	 *｛@link BeanComponentDefinition｝已注册到
	 *｛@link org.springframework.beans.factory.support.BeanDefinitionRegistry｝。
	 *＜p＞派生类可以重写此方法以提供任何自定义逻辑
	 *将在所有解析完成后执行。
	 *＜p＞默认实现是no-op。
	 *@param componentDefinition要处理的｛@link BeanComponentDefinition｝
	 */
	protected void postProcessComponentDefinition(BeanComponentDefinition componentDefinition) {
	}

}
